package com.yf.mediaserver.zlm;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.yf.mediaserver.zlm.bean.ZLMServerConfig;
import com.yf.mediaserver.zlm.bean.ZlMHookResult;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ZLMUtil {

    public static final String ZLM_IP = "192.168.1.243";
    public static final int ZPM_PORT = 80;
    public static final String SECRET = "XNcUPNMumsa0hedqcso4ZDQjmtfeqrMH";

    public static ZlMHookResult<List<String>> getApiList() {
        return JSONUtil.toBean(request(APIEnum.GET_API_LIST), new TypeReference<ZlMHookResult<List<String>>>() {
        }, false);
    }


    public static ZlMHookResult<List<String>> getThreadsLoad() {
        return JSONUtil.toBean(request(APIEnum.GET_THREADS_LOAD), new TypeReference<ZlMHookResult<List<String>>>() {
        }, false);
    }

    public static ZLMServerConfig getServerConfig() throws RuntimeException{
        ZlMHookResult<List<ZLMServerConfig>> result = getServerConfigs();
        if(result.fail()){
            throw new RuntimeException("获取到流媒体服务器信息失败");
        }
        List<ZLMServerConfig> serverList = result.getData();
        if(CollUtil.isEmpty(serverList)){
            throw new RuntimeException("获取到流媒体服务器信息");
        }
        return  serverList.get(0);
    }

    public static ZlMHookResult<List<ZLMServerConfig>> getServerConfigs() {
        String resp = request(APIEnum.GET_SERVER_CONFIG);
        return JSONUtil.toBean(resp, new TypeReference<ZlMHookResult<List<ZLMServerConfig>>>() {
        }, false);
//        return JSONUtil.toBean(resp(APIEnum.GET_SERVER_CONFIG), new TypeReference<ZlMHookResult<List<ZLMServerConfig>>>() {
//        }, false);
    }




    public static ZlMHookResult<Map<String, Integer>> getStatistic() {
        return JSONUtil.toBean(request(APIEnum.GET_STATISTIC), new TypeReference<ZlMHookResult<Map<String, Integer>>>() {
        }, false);
    }

    /**
     * 创建GB28181 RTP接收端口，如果该端口接收数据超时，则会自动被回收(不用调用closeRtpServer接口)
     * 参数	是否必选	释意
     * secret	Y	api操作密钥(配置文件配置)
     * port	Y	接收端口，0则为随机端口
     * tcp_mode	Y	0 udp 模式，1 tcp 被动模式, 2 tcp 主动模式。 (兼容enable_tcp 为0/1)
     * stream_id	Y	该端口绑定的流ID，该端口只能创建这一个流(而不是根据ssrc创建多个)
     */
    public static ZlMHookResult<?> openRtpServer(String stream_id) {

        Map<String, Object> param = new HashMap<>();
        //端口范围 35000 ~ 35100
        param.put("port", 35000 + RandomUtil.randomInt(101));
        param.put("tcp_mode", 0);
        param.put("stream_id", stream_id);
        return JSONUtil.toBean(request(APIEnum.OPEN_RTP_SERVER, param, HttpRequest::form), ZlMHookResult.class);
    }

    /**
     * 得到流列表
     * @param app 协议
     * @param vhost 虚拟主机
     * @param stream 应用名
     * @param schema 流ID
     * @return  ZLM返回列表数据
     */
    public static ZlMHookResult<?> getMediaList(
            String app,
            String vhost,
            String stream,
            String schema
    ) {
        //支持参数
        //param:app,stream,schema,vhost
        Map<String, Object> param = new HashMap<>();
        addParam(param,"app",app);
        addParam(param,"vhost",vhost);
        addParam(param,"stream",stream);
        addParam(param,"schema",schema);

        log.info("参数：{}",JSONUtil.toJsonStr(param));
        return JSONUtil.toBean(request(APIEnum.GET_MEDIA_LIST,param,HttpRequest::form), ZlMHookResult.class);
    }


    public static void  addParam(Map<String, Object> map,String key,Object v){
        if(null == v){
            return;
        }
        if(StrUtil.isBlank(key)){
            return;
        }
        map.put(key,v);
    }

    public static <T> String request(APIEnum api) {
        return request(api, null, null);
    }

    public static <T> String request(APIEnum api, T param, RequestHandel<T> handel) {
        HttpRequest request = HttpUtil.createRequest(api.getMethod(), handelUrl(api));
        if (null != handel) {
            handel.handelParam(request, param);
        }
        HttpResponse execute = request.execute();
        String resp = execute.body();
        log.debug("{} => {}", api.getDescription(), resp);
        return resp;
    }


    public interface RequestHandel<T> {
        void handelParam(HttpRequest request, T t);
    }

    public static String handelUrl(APIEnum api) {
        return String.format("http://%s:%d%s?secret=%s", ZLM_IP, ZPM_PORT, api.getPath(), SECRET);
    }


}
